/*
 *
 * Copyright (C) 2012 Walter Lütgenau
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package offset.nodes.client.vdialog.model.template;

import offset.nodes.client.model.NodeTypes;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.ResourceBundle;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.text.Document;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import offset.nodes.client.vdialog.view.template.VirtualFolderPanel;
import offset.nodes.client.vdialog.view.template.TemplatePanel;
import offset.nodes.client.vdialog.view.template.TemplateReferencePanel;
import offset.nodes.client.vdialog.view.template.VirtualPagePanel;
import offset.nodes.client.model.Server;
import offset.nodes.client.tree.model.DetailPanelTreeConfiguration;
import offset.nodes.client.tree.model.TreeNodePanel;
import offset.nodes.client.tree.model.DetailPanelTreeNodeType;
import offset.nodes.client.model.TreeNodeUserObject;
import offset.nodes.client.virtual.model.GetSchemas;
import offset.nodes.client.virtual.model.jcr.nodetype.NodeTypeDefinition;
import offset.nodes.client.virtual.model.jcr.nodetype.NodeTypeReader;

/**
 *
 * @author Walter Lütgenau
 */
public class NewTemplateConfiguration implements DetailPanelTreeConfiguration {

    JTree tree;
    Server server;
    DetailPanelTreeNodeType[] nodeTypes;
    NodeTypes types;
    URL repository;
    String path;

    public NewTemplateConfiguration(Server server, URL repository, String path) {
        this.server = server;
        this.repository = repository;
        this.path = path;
        this.nodeTypes = new DetailPanelTreeNodeType[]{
                    new Template(), new VirtualFolder(), new VirtualPage(), new TemplateReference()
                };
    }

    public NodeTypeDefinition[] initTypes() {
        GetSchemas.Request request = new GetSchemas.Request();
        GetSchemas.Response response = null;
        try {
            response = (GetSchemas.Response) server.sendRequest(request);
            InputStream in = new ByteArrayInputStream(response.getSchemaXml().getBytes());
            NodeTypeDefinition[] definitions = NodeTypeReader.read(in);

            return definitions;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public void init(JTree tree, JToolBar toolBar, JMenuBar menu) {
        this.types = new NodeTypes(initTypes());
        this.tree = tree;
        setupTree();
    }

    protected void setupTree() {
        DefaultMutableTreeNode root = new DefaultMutableTreeNode(getNodeTypes()[0].createUserObject());
        ((DefaultTreeModel) tree.getModel()).setRoot(root);
        tree.setSelectionRow(0);
    }

    public Object getResult() {
        return ((DefaultTreeModel) tree.getModel()).getRoot();
    }

    protected DetailPanelTreeNodeType getNodeType(String name) {
        for (int i = 0; i < nodeTypes.length; i++) {
            if (nodeTypes[i].getName().equals(name))
                return nodeTypes[i];
        }
        return null;
    }

    public void insertNodeAt(DefaultMutableTreeNode parent, int position, String typeName) {
        DefaultMutableTreeNode insert = new DefaultMutableTreeNode();

        DetailPanelTreeNodeType nodeType = getNodeType(typeName);
        if (nodeType == null)
            return;

        insert.setUserObject(nodeType.createUserObject());
        ((DefaultTreeModel) tree.getModel()).insertNodeInto(insert, parent, position);

        TreePath childPath = new TreePath(insert.getPath());
        tree.setSelectionPath(childPath);
    }

    public void removeNode(DefaultMutableTreeNode remove) {
        int[] selected = tree.getSelectionRows();
        ((DefaultTreeModel) tree.getModel()).removeNodeFromParent(remove);
        if (selected.length > 0 && selected[0] > 0)
            tree.setSelectionRow(selected[0] - 1);
    }

    public void writeTextualRepresentation(Document document, ResourceBundle bundle) {
        TemplateDefinitionWriter writer = new TemplateDefinitionWriter(document);
        try {
            writer.print((DefaultMutableTreeNode) ((DefaultTreeModel) tree.getModel()).getRoot());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void cancelNodeModification(DetailPanelTreeNodeType type) {
        TreePath path = tree.getSelectionPath();
        if (path == null)
            return;

        DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
        TreeNodeUserObject userObject = (TreeNodeUserObject) node.getUserObject();
        if (userObject == null)
            return;

        for (int i = 0; i < nodeTypes.length; i++) {
            if (nodeTypes[i].getName().equals(userObject.getType())) {
                TreeNodePanel panel = (TreeNodePanel) nodeTypes[i].getDetailPanel();
                panel.setPanel(userObject);
                break;
            }
        }
    }

    public void acceptNodeModification(DetailPanelTreeNodeType type) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getSelectionModel().getLeadSelectionPath().getLastPathComponent();
        node.setUserObject(((TreeNodePanel) type.getDetailPanel()).getUserObject());
    }

    public DetailPanelTreeConfiguration getModel() {
        return this;
    }

    class VirtualFolder implements DetailPanelTreeNodeType {

        Icon folderIcon = UIManager.getIcon("Tree.closedIcon");
        VirtualFolderPanel panel = new VirtualFolderPanel(server, AbstractTemplateNode.TYPE_VIRTUAL_FOLDER);

        public String getName() {
            return AbstractTemplateNode.TYPE_VIRTUAL_FOLDER;
        }

        public JPanel getDetailPanel() {
            panel.setTypes(types);
            return panel;
        }

        public Icon getIcon() {
            return folderIcon;
        }

        public TreeNodeUserObject createUserObject() {
            return new FolderNode();
        }

        public boolean canAccept(String typeName) {
            return true;
        }
    }

    class VirtualPage implements DetailPanelTreeNodeType {

        ImageIcon pageIcon = new ImageIcon(NewTemplateConfiguration.class.getResource("/offset/nodes/client/dialog/view/resources/file.png"));
        VirtualPagePanel panel = new VirtualPagePanel(server, repository, AbstractTemplateNode.TYPE_VIRTUAL_PAGE);

        public String getName() {
            return AbstractTemplateNode.TYPE_VIRTUAL_PAGE;
        }

        public JPanel getDetailPanel() {
            panel.setTypes(types);
            return panel;
        }

        public Icon getIcon() {
            return pageIcon;
        }

        public TreeNodeUserObject createUserObject() {
            return new PageNode();
        }

        public boolean canAccept(String typeName) {
            return true;
        }
    }

    class TemplateReference implements DetailPanelTreeNodeType {

        ImageIcon templateIcon = new ImageIcon(NewTemplateConfiguration.class.getResource("/offset/nodes/client/dialog/view/resources/template.png"));
        TemplateReferencePanel panel = new TemplateReferencePanel(server, AbstractTemplateNode.TYPE_TEMPLATE_REFERENCE);

        public String getName() {
            return AbstractTemplateNode.TYPE_TEMPLATE_REFERENCE;
        }

        public JPanel getDetailPanel() {
            panel.setTypes(types);
            return panel;
        }

        public Icon getIcon() {
            return templateIcon;
        }

        public TreeNodeUserObject createUserObject() {
            return new TemplateReferenceNode();
        }

        public boolean canAccept(String typeName) {
            return true;
        }
    }

    class Template implements DetailPanelTreeNodeType {

        ImageIcon templateIcon = new ImageIcon(NewTemplateConfiguration.class.getResource("/offset/nodes/client/dialog/view/resources/template.png"));
        JPanel panel = new TemplatePanel();

        public String getName() {
            return AbstractTemplateNode.TYPE_TEMPLATE;
        }

        public JPanel getDetailPanel() {
            return panel;
        }

        public Icon getIcon() {
            return templateIcon;
        }

        public TreeNodeUserObject createUserObject() {
            return new TemplateNode();
        }

        public boolean canAccept(String typeName) {
            return true;
        }
    }

    public DetailPanelTreeNodeType[] getNodeTypes() {
        return nodeTypes;
    }

    /**
     * Return the template path
     *
     * @return
     */
    public String getTemplatePath() {
        return path;
    }
}
